package com.school.sports.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.school.sports.entity.Score;
import com.school.sports.entity.User;
import com.school.sports.service.ScoreService;
import com.school.sports.common.Result;
import lombok.extern.slf4j.Slf4j;
import javax.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 成绩管理控制器
 * 提供成绩的录入、审核、公示等功能
 */
@Slf4j
@RestController
@RequestMapping("/api/scores")
public class ScoreController {

    @Autowired
    private ScoreService scoreService;

    /**
     * 分页查询成绩列表
     * @param currentPage 当前页码
     * @param pageSize 每页大小
     * @param userId 用户ID
     * @param projectId 项目ID
     * @param refereeId 裁判ID
     * @param status 成绩状态
     * @param projectName 项目名称（模糊查询）
     * @param userName 用户姓名（模糊查询）
     * @return 分页结果
     */
    @GetMapping("/page/{currentPage}/{pageSize}")
    @PreAuthorize("hasAnyRole('管理员', '老师', '裁判', '学生')")
    public Result<IPage<Score>> getScorePage(
            @PathVariable("currentPage") Integer currentPage,
            @PathVariable("pageSize") Integer pageSize,
            @RequestParam(value = "userId", required = false) Long userId,
            @RequestParam(value = "projectId", required = false) Long projectId,
            @RequestParam(value = "refereeId", required = false) Long refereeId,
            @RequestParam(value = "status", required = false) String status,
            @RequestParam(value = "projectName", required = false) String projectName,
            @RequestParam(value = "userName", required = false) String userName) {

        log.info("分页查询成绩列表，当前页码：{}，每页条数：{}，查询条件：userId={}, projectId={}, refereeId={}, status={}, projectName={}, userName={}",
                currentPage, pageSize, userId, projectId, refereeId, status, projectName, userName);

        try {
            Page<Score> page = new Page<>(currentPage, pageSize);
            LambdaQueryWrapper<Score> queryWrapper = new LambdaQueryWrapper<>();

            // 构建查询条件
            queryWrapper.eq(userId != null, Score::getUserId, userId)
                    .eq(projectId != null, Score::getProjectId, projectId)
                    .eq(refereeId != null, Score::getRefereeId, refereeId)
                    .eq(StringUtils.hasText(status), Score::getStatus, status)
                    .orderByDesc(Score::getCreatedAt);

            IPage<Score> scorePage = scoreService.page(page, queryWrapper);
            log.info("查询成绩列表成功，共{}条记录", scorePage.getTotal());
            return Result.success(scorePage);
        } catch (Exception e) {
            log.error("查询成绩列表异常：{}", e.getMessage(), e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 根据ID查询成绩详情
     * @param scoreId 成绩ID
     * @return 成绩详情
     */
    @GetMapping("/{scoreId}")
    @PreAuthorize("hasAnyRole('管理员', '老师', '裁判', '学生')")
    public Result<Score> getScoreById(@PathVariable("scoreId") Long scoreId) {
        log.info("查询成绩详情，成绩ID：{}", scoreId);

        if (scoreId == null || scoreId <= 0) {
            return Result.fail("成绩ID无效");
        }

        try {
            Score score = scoreService.getScoreWithDetails(scoreId);
            if (score == null) {
                return Result.fail("成绩不存在");
            }
            log.info("查询成绩详情成功，成绩ID：{}", scoreId);
            return Result.success(score);
        } catch (Exception e) {
            log.error("查询成绩详情异常：{}", e.getMessage(), e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 录入成绩
     * @param score 成绩信息
     * @return 操作结果
     */
    @PostMapping
    @PreAuthorize("hasAnyRole('管理员', '老师', '裁判')")
    public Result<String> recordScore(@Valid @RequestBody Score score) {
        log.info("录入成绩：项目ID={}，用户ID={}，轮次={}，成绩={}",
                score.getProjectId(), score.getUserId(), score.getRound(), score.getScoreValue());

        try {
            // 设置录入裁判和状态
            User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            score.setRefereeId(currentUser.getId());
            score.setStatus("待审核");

            boolean success = scoreService.recordScore(score);
            if (success) {
                log.info("成绩录入成功");
                return Result.success("录入成功，请等待审核");
            } else {
                return Result.fail("录入失败，请检查成绩有效性");
            }
        } catch (Exception e) {
            log.error("录入成绩异常：{}", e.getMessage(), e);
            return Result.fail("录入失败：" + e.getMessage());
        }
    }

    /**
     * 更新成绩信息
     * @param score 成绩信息
     * @return 操作结果
     */
    @PutMapping
    @PreAuthorize("hasAnyRole('管理员', '老师', '裁判')")
    public Result<String> updateScore(@Valid @RequestBody Score score) {
        log.info("更新成绩信息：ID={}", score.getId());

        try {
            boolean success = scoreService.updateScore(score);
            if (success) {
                log.info("更新成绩成功");
                return Result.success("更新成功");
            } else {
                return Result.fail("更新失败，请检查状态权限");
            }
        } catch (Exception e) {
            log.error("更新成绩异常：{}", e.getMessage(), e);
            return Result.fail("更新失败：" + e.getMessage());
        }
    }

    /**
     * 删除成绩
     * @param scoreId 成绩ID
     * @return 操作结果
     */
    @DeleteMapping("/{scoreId}")
    @PreAuthorize("hasAnyRole('管理员', '老师', '裁判')")
    public Result<String> deleteScore(@PathVariable("scoreId") Long scoreId) {
        log.info("删除成绩，ID：{}", scoreId);

        if (scoreId == null || scoreId <= 0) {
            return Result.fail("成绩ID无效");
        }

        try {
            boolean success = scoreService.deleteScore(scoreId);
            if (success) {
                log.info("删除成绩成功");
                return Result.success("删除成功");
            } else {
                return Result.fail("删除失败，请检查状态权限");
            }
        } catch (Exception e) {
            log.error("删除成绩异常：{}", e.getMessage(), e);
            return Result.fail("删除失败：" + e.getMessage());
        }
    }

    /**
     * 审核成绩
     * @param scoreId 成绩ID
     * @param status 审核结果
     * @param note 审核意见
     * @return 操作结果
     */
    @PutMapping("/{scoreId}/audit")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<String> auditScore(
            @PathVariable("scoreId") Long scoreId,
            @RequestParam("status") String status,
            @RequestParam(value = "note", required = false) String note) {

        log.info("审核成绩，成绩ID：{}，审核结果：{}，审核意见：{}", scoreId, status, note);

        if (scoreId == null || scoreId <= 0) {
            return Result.fail("成绩ID无效");
        }

        if (!isValidStatus(status)) {
            return Result.fail("审核结果不合法");
        }

        try {
            boolean success = scoreService.auditScore(scoreId, status, note);
            if (success) {
                log.info("审核成绩成功，成绩ID：{}", scoreId);
                return Result.success("审核成功");
            } else {
                return Result.fail("审核失败，请检查状态权限");
            }
        } catch (Exception e) {
            log.error("审核成绩异常：{}", e.getMessage(), e);
            return Result.fail("审核失败：" + e.getMessage());
        }
    }

    /**
     * 批量审核成绩
     * @param scoreIds 成绩ID列表
     * @param status 审核结果
     * @param note 审核意见
     * @return 操作结果
     */
    @PutMapping("/batch-audit")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<String> batchAuditScores(
            @RequestBody List<Long> scoreIds,
            @RequestParam("status") String status,
            @RequestParam(value = "note", required = false) String note) {

        log.info("批量审核成绩，成绩ID列表：{}，审核结果：{}", scoreIds, status);

        if (scoreIds == null || scoreIds.isEmpty()) {
            return Result.fail("请选择要审核的成绩记录");
        }

        if (!isValidStatus(status)) {
            return Result.fail("审核结果不合法");
        }

        try {
            boolean success = scoreService.batchAuditScores(scoreIds, status, note);
            if (success) {
                log.info("批量审核成绩成功，共{}条记录", scoreIds.size());
                return Result.success("批量审核成功");
            } else {
                return Result.fail("批量审核部分失败");
            }
        } catch (Exception e) {
            log.error("批量审核成绩异常：{}", e.getMessage(), e);
            return Result.fail("批量审核失败：" + e.getMessage());
        }
    }

    /**
     * 公示成绩
     * @param scoreId 成绩ID
     * @return 操作结果
     */
    @PutMapping("/{scoreId}/publish")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<String> publishScore(@PathVariable("scoreId") Long scoreId) {
        log.info("公示成绩，成绩ID：{}", scoreId);

        try {
            boolean success = scoreService.publishScore(scoreId);
            if (success) {
                log.info("公示成绩成功，成绩ID：{}", scoreId);
                return Result.success("公示成功");
            } else {
                return Result.fail("公示失败，请检查状态权限");
            }
        } catch (Exception e) {
            log.error("公示成绩异常：{}", e.getMessage(), e);
            return Result.fail("公示失败：" + e.getMessage());
        }
    }

    /**
     * 批量公示成绩
     * @param scoreIds 成绩ID列表
     * @return 操作结果
     */
    @PutMapping("/batch-publish")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<String> batchPublishScores(@RequestBody List<Long> scoreIds) {
        log.info("批量公示成绩，成绩ID列表：{}", scoreIds);

        if (scoreIds == null || scoreIds.isEmpty()) {
            return Result.fail("请选择要公示的成绩记录");
        }

        try {
            boolean success = scoreService.batchPublishScores(scoreIds);
            if (success) {
                log.info("批量公示成绩成功，共{}条记录", scoreIds.size());
                return Result.success("批量公示成功");
            } else {
                return Result.fail("批量公示部分失败");
            }
        } catch (Exception e) {
            log.error("批量公示成绩异常：{}", e.getMessage(), e);
            return Result.fail("批量公示失败：" + e.getMessage());
        }
    }

    /**
     * 根据用户ID查询成绩列表
     * @param userId 用户ID
     * @return 成绩列表
     */
    @GetMapping("/user/{userId}")
    @PreAuthorize("hasAnyRole('管理员', '老师', '裁判', '学生')")
    public Result<List<Score>> getScoresByUserId(@PathVariable("userId") Long userId) {
        log.info("根据用户ID查询成绩列表，用户ID：{}", userId);

        try {
            List<Score> scores = scoreService.getScoresByUserId(userId);
            log.info("查询成绩列表成功，共{}条记录", scores.size());
            return Result.success(scores);
        } catch (Exception e) {
            log.error("查询成绩列表异常：{}", e.getMessage(), e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 根据项目ID查询成绩列表
     * @param projectId 项目ID
     * @return 成绩列表
     */
    @GetMapping("/project/{projectId}")
    @PreAuthorize("hasAnyRole('管理员', '老师', '裁判', '学生')")
    public Result<List<Score>> getScoresByProjectId(@PathVariable("projectId") Long projectId) {
        log.info("根据项目ID查询成绩列表，项目ID：{}", projectId);

        try {
            List<Score> scores = scoreService.getScoresByProjectId(projectId);
            log.info("查询成绩列表成功，共{}条记录", scores.size());
            return Result.success(scores);
        } catch (Exception e) {
            log.error("查询成绩列表异常：{}", e.getMessage(), e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 获取成绩状态列表
     * @return 成绩状态列表
     */
    @GetMapping("/statuses")
    @PreAuthorize("hasAnyRole('管理员', '老师', '裁判', '学生')")
    public Result<List<String>> getScoreStatuses() {
        log.info("获取成绩状态列表");

        try {
            List<String> statuses = scoreService.getAllScoreStatuses();
            log.info("获取成绩状态列表成功，共{}种状态", statuses.size());
            return Result.success(statuses);
        } catch (Exception e) {
            log.error("获取成绩状态列表异常：{}", e.getMessage(), e);
            return Result.fail("获取失败：" + e.getMessage());
        }
    }

    /**
     * 根据状态查询成绩列表
     * @param status 成绩状态
     * @return 成绩列表
     */
    @GetMapping("/status/{status}")
    @PreAuthorize("hasAnyRole('管理员', '老师', '裁判', '学生')")
    public Result<List<Score>> getScoresByStatus(@PathVariable("status") String status) {
        log.info("根据状态查询成绩列表，状态：{}", status);

        if (!StringUtils.hasText(status)) {
            return Result.fail("状态参数不能为空");
        }

        try {
            List<Score> scores = scoreService.getScoresByStatus(status);
            log.info("查询成绩列表成功，共{}条记录", scores.size());
            return Result.success(scores);
        } catch (Exception e) {
            log.error("查询成绩列表异常：{}", e.getMessage(), e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 获取成绩统计信息
     * @param projectId 项目ID（可选）
     * @return 统计信息
     */
    @GetMapping("/statistics")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<Map<String, Object>> getScoreStatistics(
            @RequestParam(value = "projectId", required = false) Long projectId) {

        log.info("获取成绩统计信息，项目ID：{}", projectId);

        try {
            Map<String, Object> statistics = scoreService.getScoreStatistics(projectId);
            log.info("获取成绩统计信息成功");
            return Result.success(statistics);
        } catch (Exception e) {
            log.error("获取成绩统计信息异常：{}", e.getMessage(), e);
            return Result.fail("获取失败：" + e.getMessage());
        }
    }

    /**
     * 计算项目排名
     * @param projectId 项目ID
     * @param round 轮次
     * @return 排名结果
     */
    @PostMapping("/calculate-rankings")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<String> calculateRankings(
            @RequestParam("projectId") Long projectId,
            @RequestParam("round") Integer round) {

        log.info("计算项目排名，项目ID：{}，轮次：{}", projectId, round);

        try {
            boolean success = scoreService.autoCalculateRankings(projectId, round);
            if (success) {
                log.info("计算排名成功");
                return Result.success("排名计算成功");
            } else {
                return Result.fail("排名计算失败");
            }
        } catch (Exception e) {
            log.error("计算排名异常：{}", e.getMessage(), e);
            return Result.fail("排名计算失败：" + e.getMessage());
        }
    }

    /**
     * 获取项目排名
     * @param projectId 项目ID
     * @param round 轮次
     * @return 排名列表
     */
    @GetMapping("/rankings/{projectId}/{round}")
    @PreAuthorize("hasAnyRole('管理员', '老师', '裁判', '学生')")
    public Result<List<com.school.sports.entity.Rank>> getRankings(
            @PathVariable("projectId") Long projectId,
            @PathVariable("round") Integer round) {

        log.info("获取项目排名，项目ID：{}，轮次：{}", projectId, round);

        try {
            List<com.school.sports.entity.Rank> rankings = scoreService.getRankingsByProject(projectId, round);
            log.info("获取项目排名成功，共{}条记录", rankings.size());
            return Result.success(rankings);
        } catch (Exception e) {
            log.error("获取项目排名异常：{}", e.getMessage(), e);
            return Result.fail("获取排名失败：" + e.getMessage());
        }
    }

    /**
     * 获取个人成绩统计
     * @param userId 用户ID
     * @return 个人统计信息
     */
    @GetMapping("/personal-statistics/{userId}")
    @PreAuthorize("hasAnyRole('管理员', '老师', '学生')")
    public Result<Map<String, Object>> getPersonalStatistics(@PathVariable("userId") Long userId) {
        log.info("获取个人成绩统计，用户ID：{}", userId);

        try {
            Map<String, Object> statistics = scoreService.getPersonalScoreStatistics(userId);
            log.info("获取个人成绩统计成功");
            return Result.success(statistics);
        } catch (Exception e) {
            log.error("获取个人成绩统计异常：{}", e.getMessage(), e);
            return Result.fail("获取失败：" + e.getMessage());
        }
    }

    /**
     * 获取奖牌统计
     * @param projectId 项目ID（可选）
     * @return 奖牌统计
     */
    @GetMapping("/medal-statistics")
    @PreAuthorize("hasAnyRole('管理员', '老师', '学生')")
    public Result<Map<String, Integer>> getMedalStatistics(
            @RequestParam(value = "projectId", required = false) Long projectId) {

        log.info("获取奖牌统计，项目ID：{}", projectId);

        try {
            Map<String, Integer> statistics = scoreService.getMedalStatistics(projectId);
            log.info("获取奖牌统计成功");
            return Result.success(statistics);
        } catch (Exception e) {
            log.error("获取奖牌统计异常：{}", e.getMessage(), e);
            return Result.fail("获取失败：" + e.getMessage());
        }
    }

    /**
     * 校验状态合法性
     */
    private boolean isValidStatus(String status) {
        return Arrays.asList("待审核", "已公示", "已驳回", "有异议").contains(status);
    }
}